package com.yxw.live_vod_backend_boot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.live_vod_backend_boot.dto.*;
import com.yxw.live_vod_backend_boot.entity.YxProductCategoryEntity;
import com.yxw.live_vod_backend_boot.entity.YxProductEntity;
import com.yxw.live_vod_backend_boot.mapper.ProductCategoryMapper;
import com.yxw.live_vod_backend_boot.mapper.ProductMapper;
import com.yxw.live_vod_backend_boot.mapper.ProductSpecificationMapper;
import com.yxw.live_vod_backend_boot.service.FileService;
import com.yxw.live_vod_backend_boot.service.ProductService;
import com.yxw.live_vod_backend_boot.util.PageUtils;
import com.yxw.live_vod_backend_boot.util.RedisManager;
import com.yxw.live_vod_backend_boot.vo.ProductSpecificationVO;
import com.yxw.live_vod_backend_boot.vo.ProductVO;
import com.yxw.live_vod_facade.dto.FileDTO;
import com.yxw.live_vod_facade.feign.OrderFeignClient;
import com.yxw.live_vod_facade.feign.ShopFeignClient;
import com.yxw.live_vod_facade.feign.UserFeignClient;
import com.yxw.live_vod_facade.vo.OrderVO;
import com.yxw.live_vod_facade.vo.ShopHomePageVO;
import com.yxw.live_vod_facade.vo.UserInfoVo;
import com.yxw.live_vod_facade.vo.YxFileVo;
import com.yxw.yxnet_cd_center.common.constant.CommonConstant;
import com.yxw.yxnet_cd_center.common.constant.RedisIdConstant;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import com.yxw.yxnet_cd_center.common.utils.BaseResult;
import com.yxw.yxnet_cd_center.common.utils.RandomCharacterUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 商品管理
 * @author xiexuxin
 * @date 2023-12-07
 */
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, YxProductEntity> implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ShopFeignClient shopFeignClient;

    @Autowired
    private ProductCategoryMapper categoryMapper;

    @Autowired
    private FileService fileService;

    @Autowired
    private OrderFeignClient orderFeignClient;

    @Autowired
    private RedisManager redisManager;

    @Autowired
    private ProductSpecificationMapper productSpecificationMapper;

    @Autowired
    private UserFeignClient userFeignClient;

    /**
     * 添加商品
     * @param addDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ProductVO> addProduct(ProductAddDTO addDTO) {
        String number = RandomCharacterUtil.generateBatchNumber();
        List<YxProductEntity> productList = new ArrayList<>();
        // 获取商店主页信息、商品分类
        BaseResult<ShopHomePageVO> shopHomePage = shopFeignClient.getShopHomePage(addDTO.getShopId());
        ShopHomePageVO shopVO = shopHomePage.getData();
        YxProductCategoryEntity category = categoryMapper.selectById(addDTO.getCategoryId());
        BaseResult<UserInfoVo> userInfo = userFeignClient.getUserInfo(Long.parseLong(addDTO.getUserId()));
        if (category == null) {
            throw new BaseException("商品分类不存在");
        }
        String[] productMasterPic = addDTO.getProductMasterPic();
        String[] productDetailPic = addDTO.getProductDetailPic();
        String productMasterPicStr = String.join(",", productMasterPic);
        String productDetailPicStr = String.join(",", productDetailPic);
        for (ProductAddsDTO adds : addDTO.getAddsDTO()){
            // 检查商品编号是否重复
            YxProductEntity productEntity = baseMapper.selectOne(new QueryWrapper<YxProductEntity>().eq("product_num", adds.getProductNum()));
            if (productEntity != null) {
                throw new BaseException("【" + adds.getProductNum() + "】商品编号已重复，请重新输入");
            }
            YxProductEntity product = new YxProductEntity();
            BeanUtils.copyProperties(addDTO, product);
            BeanUtils.copyProperties(adds, product);
            product.setProductMasterPic(productMasterPicStr);
            product.setProductDetailPic(productDetailPicStr);
            product.setUserId(userInfo.getData().getUserId());
            product.setUserName(userInfo.getData().getUserName());
            product.setShopId(shopVO.getLiveShopId());
            product.setShopName(shopVO.getShopName());
            product.setStyle(adds.getStyle());
            product.setProductNum(adds.getProductNum() + "-" + addDTO.getShopId());
            product.setPicBussId(Long.parseLong(addDTO.getPicBussId()));
            product.setCategoryId(Long.parseLong(addDTO.getCategoryId()));
            product.setProductCategory(category.getCategoryName());
            product.setProductSeriesNum(addDTO.getProductName() + "-" + number);
            product.setProductStatus(CommonConstant.ZERO);
            product.setPreeCnt(CommonConstant.ZERO);
            product.setUseCnt(CommonConstant.ZERO);
            product.setCreateTime(new Date());
            productList.add(product);
        }
        if (!CollectionUtils.isEmpty(productList)) {
            productMapper.batchInsertProduct(productList);
        }
        List<ProductVO> productByNum = productMapper.getProductByNum(number);
        Set<Long> uniqueProductIds = new HashSet<>();
        for (ProductVO vo : productByNum) {
            Long productId = vo.getProductId();
            uniqueProductIds.add(productId);
        }
        List<ProductVO> voList = new ArrayList<>();
        for (Long id : uniqueProductIds){
            if (id != null){
                YxProductEntity product = productMapper.selectById(id);
                if (product != null) {
                    redisManager.set(RedisIdConstant.PRODUCT_TOTAL_CNT + ":" + product.getProductId(), product.getTotalCnt());
                    ProductVO vo = new ProductVO();
                    BeanUtils.copyProperties(product, vo);
                    voList.add(vo);
                }
            }
        }
        return voList;
    }

    /**
     * 删除商品
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProduct(ProductDeleteDTO dto) {
        if (CollectionUtils.isEmpty(dto.getProductIds())) {
            throw new BaseException("删除商品失败，尝试删除的商品数据不存在，请稍后再试！");
        }
        for (String productId : dto.getProductIds()) {
            Integer orderStatus = getOrderStatus(Long.valueOf(productId));
            if (orderStatus == 0 || orderStatus == 1) {
              throw new BaseException("删除商品失败,该商品还存在未处理的订单,请先将商品下架,订单处理完成后再次删除!");
            }
            YxProductEntity product = productMapper.selectById(productId);
            if (product != null) {
                // 删除文件表中的商品主图与详图
                if (product.getPicBussId() != null){
                    BaseResult<List<YxFileVo>> list = fileService.getFileListByBussId(product.getPicBussId());
                    List<YxFileVo> data = list.getData();
                    List<Long> picIds = new ArrayList<>();
                    for (YxFileVo vo : data){
                        picIds.add(vo.getId());
                    }
                    FileDTO fileDTO = new FileDTO();
                    fileDTO.setObjId(product.getPicBussId());
                    fileDTO.setFileIdList(picIds);
                    fileService.deleteFile(fileDTO);
                }
            }
            getProductStock(productId);
            delStock(Long.valueOf(productId));
        }
        // 执行删除操作
        baseMapper.deleteBatchIds(dto.getProductIds());
    }

    /**
     * 获取订单状态
     * @param productId
     * @return
     */
    private Integer getOrderStatus(Long productId) {
        BaseResult<List<OrderVO>> orderList = orderFeignClient.getOrderByProduct(productId);
        if (orderList == null || orderList.getData().isEmpty()) {
            return 0;
        }
        Optional<Integer> optionalOrderStatus = orderList.getData()
                .stream()
                .map(OrderVO::getOrderStatus)
                .filter(status -> status == 0 || status == 1)
                .findFirst();
        return optionalOrderStatus.orElse(0);
    }

    /**
     * 修改商品
     * @param updateDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProduct(ProductUpdateDTO updateDTO) {
        YxProductEntity product = productMapper.selectById(updateDTO.getProductId());
        if (product == null){
            throw new BaseException("商品不存在,服务器忙,请稍后再试!");
        }
        YxProductEntity existProduct = baseMapper.selectOne(new QueryWrapper<YxProductEntity>().eq("product_num", updateDTO.getProductNum()));
        if (existProduct != null) {
            throw new BaseException("【"+updateDTO.getProductNum()+"】商品编号已重复，请重新输入");
        }
        // 删除原来的商品主图与详图
        if (product.getPicBussId() != null){
            BaseResult<List<YxFileVo>> list = fileService.getFileListByBussId(product.getPicBussId());
            List<YxFileVo> data = list.getData();
            List<Long> picIds = new ArrayList<>();
            for (YxFileVo vo : data){
                picIds.add(vo.getId());
            }
            FileDTO fileDTO = new FileDTO();
            fileDTO.setObjId(product.getPicBussId());
            fileDTO.setFileIdList(picIds);
            fileService.deleteFile(fileDTO);
        }
        String[] productMasterPic = updateDTO.getProductMasterPic();
        String[] productDetailPic = updateDTO.getProductDetailPic();
        String productMasterPicStr = String.join(",", productMasterPic);
        String productDetailPicStr = String.join(",", productDetailPic);
        BeanUtils.copyProperties(updateDTO,product);
        YxProductCategoryEntity category = categoryMapper.selectById(updateDTO.getCategoryId());
        product.setProductMasterPic(productMasterPicStr);
        product.setProductDetailPic(productDetailPicStr);
        product.setCategoryId(Long.parseLong(updateDTO.getCategoryId()));
        product.setProductCategory(category.getCategoryName());
        product.setPicBussId(Long.parseLong(updateDTO.getPicBussId()));
        product.setUpdateTime(new Date());
        baseMapper.updateById(product);
        redisManager.set(RedisIdConstant.PRODUCT_TOTAL_CNT + ":" + product.getProductId(), updateDTO.getTotalCnt());
    }

    /**
     * 获取商品列表
     * @param queryDTO
     * @return
     */
    @Override
    public PageVO<ProductVO> getProductList(ProductQueryDTO queryDTO) {
        Page<YxProductEntity> page = new Page<>(queryDTO.getCurrPage(), queryDTO.getPageSize());
        LambdaQueryWrapper<YxProductEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(queryDTO.getProductName()), YxProductEntity::getProductName, queryDTO.getProductName())
                .like(StringUtils.isNotBlank(queryDTO.getShopName()), YxProductEntity::getShopName, queryDTO.getShopName())
                .eq(StringUtils.isNotBlank(queryDTO.getProductSeriesNum()), YxProductEntity::getProductSeriesNum, queryDTO.getProductSeriesNum())
                .eq(queryDTO.getProductStatus() != null,YxProductEntity::getProductStatus, queryDTO.getProductStatus())
                .eq(queryDTO.getShopId() != null, YxProductEntity::getShopId, queryDTO.getShopId());
        page = baseMapper.selectPage(page, queryWrapper);
        List<YxProductEntity> entityList = page.getRecords();
        List<ProductVO> listVoList = new ArrayList<>();
        if (null != entityList && !entityList.isEmpty()) {
            listVoList = BeanUtil.copyToList(entityList, ProductVO.class);
        }
        return PageUtils.get(page, listVoList);
    }

    /**
     * 根据Id获取商品详情
     * @param productId
     * @return
     */
    @Override
    public ProductVO getProductById(String productId) {
        YxProductEntity product = baseMapper.selectById(productId);
        String[] detailPics = product.getProductDetailPic().split(",");
        String[] masterPics = product.getProductMasterPic().split(",");
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(product, productVO);
        productVO.setProductDetailPic(detailPics);
        productVO.setProductMasterPic(masterPics);
        return productVO;
    }

    /**
     * 获取规格相关的商品列表
     * @param productSeriesNum
     * @return
     */
    @Override
    public List<ProductVO> getProductByNum(String productSeriesNum) {
        return productMapper.getProductByNum(productSeriesNum);
    }

    /**
     * 商品上架/下架
     * @param productId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void isPutAwayById(String productId, Integer productStatus) {
        YxProductEntity product = baseMapper.selectById(productId);
        if (product == null) {
            throw new BaseException("商品不存在!");
        }
        if (productStatus == null) {
            throw new BaseException("商品的状态为空!");
        }
        if (product.getProductStatus() == 1 && productStatus == 1){
            throw new BaseException("当前商品已经处于下架状态");
        }
        if (productStatus == 1) {
            getProductStock(productId);
            delStock(Long.parseLong(productId));
            product.setProductStatus(CommonConstant.ONE);
        }
        if (productStatus == 0) {
            if (product.getTotalCnt() == 0) {
                throw new BaseException("当前商品库存为空,不可上架");
            }
            product.setProductStatus(CommonConstant.ZERO);
        }
        baseMapper.updateById(product);
    }

    /**
     * 将redis中的库存相关取出并保存到数据库
     * @param productId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getProductStock(String productId) {
        YxProductEntity productEntity = productMapper.selectById(productId);
        if (productEntity == null){
            throw new BaseException("商品不存在!");
        }
        String totalCntKey = RedisIdConstant.PRODUCT_TOTAL_CNT + ":" + productId;
        String preeCntKey = RedisIdConstant.PRODUCT_PREE_CNT + ":" + productId;
        String useCntKey = RedisIdConstant.PRODUCT_USE_CNT + ":" + productId;
        // 查询总库存
        int totalCnt = getIntegerFromRedis(totalCntKey);
        if (totalCnt < 0) {
            throw new BaseException("无效的totalCnt值: " + totalCnt);
        }
        // 查询预占库存
        int preeCnt = getIntegerFromRedis(preeCntKey);
        if (preeCnt < 0) {
            throw new BaseException("无效的preeCnt值: " + preeCnt);
        }
        // 查询实占库存
        int useCnt = getIntegerFromRedis(useCntKey);
        if (useCnt < 0) {
            throw new BaseException("无效的useCnt值: " + useCnt);
        }
        // 将库存信息更新到数据库中
        YxProductEntity product = baseMapper.selectById(productId);
        if (product == null) {
            throw new BaseException("商品不存在!");
        }
        product.setTotalCnt(totalCnt);
        product.setPreeCnt(preeCnt);
        product.setUseCnt(useCnt);
        baseMapper.updateById(product);
    }

    /**
     * 根据商品ID获取对应商品规格列表信息
     * @param productId
     * @return
     */
    @Override
    public List<ProductSpecificationVO> getProductSpecificationById(String productId) {
        return productSpecificationMapper.getProductSpecificationsByProductId(Long.valueOf(productId));
    }

    /**
     * 删除redis中的缓存信息
     * @param productId
     */
    private void delStock(Long productId){
        String totalCntKey = RedisIdConstant.PRODUCT_TOTAL_CNT + ":" + productId;
        String preeCntKey = RedisIdConstant.PRODUCT_PREE_CNT + ":" + productId;
        String useCntKey = RedisIdConstant.PRODUCT_USE_CNT + ":" + productId;
        // 删除redis中保存的库存信息
        redisManager.del(totalCntKey);
        redisManager.del(preeCntKey);
        redisManager.del(useCntKey);
    }


    /**
     * 查询Redis中的值并将其转换为整数
     * @param key
     * @return
     */
    private int getIntegerFromRedis(String key) {
        Object obj = redisManager.get(key);
        if (obj == null) {
            return 0;
        }
        try {
            return Integer.parseInt(obj.toString());
        } catch (NumberFormatException e) {
            log.error("无法将{}转换为整数", obj, e);
            throw new BaseException("转换失败");
        }
    }

}
